﻿using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace EarthWorm
{
	/// <summary>
	/// MainWindow.xaml 的交互逻辑
	/// </summary>
	public partial class MainWindow : Window
	{
		public MainWindow()
		{
			InitializeComponent();
			DataManager.GetInstance().InitConfig();
			CompareVersions();
		}

		~MainWindow()
		{
			DataManager.GetInstance().Uninit();
		}

		private void CompareVersions()
		{
			string exeName = DataManager.GetInstance().mExeName;
			string exeTarget = DataManager.GetInstance().mExeTarget;
			string downloadToPath = DataManager.GetInstance().mLocalDir;
			string remoteIniURL = DataManager.GetInstance().mIniServerURL;


			if (!downloadToPath.EndsWith("\\")) downloadToPath += "\\";
			if (!remoteIniURL.EndsWith("/")) remoteIniURL += "/";

			textBlock.Text = "检查软件版本...";
			string downloadFileUrl = GetDownloadUrl(remoteIniURL + DataManager.GetInstance().mRemoteDownloadUrlFile);
			if (downloadFileUrl != null && !downloadFileUrl.EndsWith("/")) downloadFileUrl += "/";
			string localVersion = Versions.LocalVersion(downloadToPath + "\\" + DataManager.GetInstance().mLocalVerFile);
			string remoteVersion = Versions.RemoteVersion(remoteIniURL + DataManager.GetInstance().mRemoteVerFile);

			string exePath = downloadToPath + localVersion + "\\" + exeTarget; // Download folder\version\ + executable
			string remoteFile = "";
			if (downloadFileUrl != null && remoteVersion != null)
			{
				remoteFile = downloadFileUrl + remoteVersion + ".zip";
			}

			this.Title = exeName + "：当前版本：" + (localVersion == null ? "NULL" : localVersion) + "，服务器最新版本：" + (remoteVersion == null ? "NULL" : remoteVersion);

			if (remoteVersion != null)
			{
				if (localVersion != remoteVersion)
				{
					textBlock.Text = "发现新版本，开始下载...";
					BeginDownload(remoteFile, downloadToPath, remoteVersion, exeTarget);
					return; //return, will launch after download complete
				}
			}

			// Normally startup local app
			if (new System.IO.FileInfo(exePath).Exists)
			{
				textBlock.Text = "完成";
				progressBar.Value = 100;
				LaunchExternalTool(exePath, "");
				this.Close();
			}
			else
			{
				// local file not exist, re-download if remote OK
				if (remoteVersion != null && downloadFileUrl != null)
				{
					textBlock.Text = "重新下载软件...";
					BeginDownload(remoteFile, downloadToPath, remoteVersion, exeTarget);
				}
				else
				{
					textBlock.Text = "程序不存在";
					MessageBox.Show("Program not exist.");
				}
			}
		}

		private void BeginDownload(string remoteURL, string downloadToPath, string version, string executeTarget)
		{
			string filePath = Versions.CreateTargetLocation(downloadToPath, version);
			Uri remoteURI = new Uri(remoteURL);
			//System.Net.WebClient downloader = new System.Net.WebClient();
			WebClientEx downloader = new WebClientEx(0, 0);

			downloader.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(downloader_DownloadFileCompleted);
			downloader.DownloadProgressChanged += new System.Net.DownloadProgressChangedEventHandler(downloader_DownloadFileProgressChanged);

			downloader.DownloadFileAsync(remoteURI, filePath + ".zip",
				new string[] { version, downloadToPath, executeTarget, remoteURL });
		}

		void downloader_DownloadFileProgressChanged(object sender, System.Net.DownloadProgressChangedEventArgs e)
		{
			Console.WriteLine("{0}    downloaded {1} of {2} bytes. {3} % complete...",
				(string)e.UserState.ToString(),
				e.BytesReceived,
				e.TotalBytesToReceive,
				e.ProgressPercentage);
			SynchronizationContext ctx = SynchronizationContext.Current ?? new SynchronizationContext();
			ctx?.Post(new SendOrPostCallback((o) =>
			{
				progressBar.Value = e.ProgressPercentage;
			}), null);
		}

		void downloader_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
		{
			string[] us = (string[])e.UserState;
			string currentVersion = us[0];
			string downloadToPath = us[1];
			string executeTarget = us[2];
			string remoteURL = us[3];

			if (!downloadToPath.EndsWith("\\")) // Give a trailing \ if there isn't one
				downloadToPath += "\\";

			string zipName = downloadToPath + currentVersion + ".zip"; // Download folder + zip file
			string exePath = downloadToPath + currentVersion + "\\" + executeTarget; // Download folder\version\ + executable

			if (e.Error == null)
			{
				try
				{
					if (new System.IO.FileInfo(zipName).Exists)
					{
						SynchronizationContext ctx = SynchronizationContext.Current ?? new SynchronizationContext();
						ctx?.Post(new SendOrPostCallback((o) =>
						{
							textBlock.Text = "下载完成，开始解压...";
						}), null);


						System.IO.Directory.Delete(downloadToPath + currentVersion, true);

						using (var zip = ZipFile.Open(zipName, ZipArchiveMode.Read))
						{
							zip.ExtractToDirectory(downloadToPath + currentVersion);
						}

						if (new System.IO.FileInfo(exePath).Exists)
						{
							Versions.CreateLocalVersionFile(downloadToPath, "version.txt", currentVersion);
							LaunchExternalTool(exePath, "");
							ctx?.Post(new SendOrPostCallback((o) =>
							{
								textBlock.Text = "完成";
								this.Close();
							}), null);
						}
						else
						{
							textBlock.Text = "目标执行文件不存在：" + exePath;
							MessageBox.Show("Problem with download. Target file does not exist.");
						}
					}
					else
					{
						textBlock.Text = "版本文件不存在：" + zipName;
						MessageBox.Show("Problem with download. Release file does not exist.");
					}
				}
				catch (Exception ex)
				{
					MessageBox.Show("Exception when process download file:" + ex.Message);
				}
			}
			else
			{
				textBlock.Text = "下载失败：" + remoteURL;
				MessageBox.Show("Problem with download. Server failed.");
			}
		}

		private void LaunchExternalTool(string exepath, string args)
		{
			using (System.Diagnostics.Process pProcess = new System.Diagnostics.Process())
			{
				pProcess.StartInfo.FileName = exepath;
				pProcess.StartInfo.Arguments = args;
				pProcess.StartInfo.UseShellExecute = false;
				pProcess.StartInfo.RedirectStandardOutput = false;
				pProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
				pProcess.StartInfo.CreateNoWindow = true; //not diplay a windows
				pProcess.Start();
				//string output = pProcess.StandardOutput.ReadToEnd(); //The output result
				//pProcess.WaitForExit();
			}
		}

		public string GetDownloadUrl(string url)
		{
			string rv = "";

			try
			{
				System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)
				System.Net.WebRequest.Create(url);
				System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)req.GetResponse();
				System.IO.Stream receiveStream = response.GetResponseStream();
				System.IO.StreamReader readStream = new System.IO.StreamReader(receiveStream, Encoding.GetEncoding("GBK"));
				string s = readStream.ReadToEnd().Trim();
				response.Close();
				if (s.Length > 0)
				{
					rv = s;
				}
			}
			catch (Exception)
			{
				// Anything could have happened here but 
				// we don't want to stop the user
				// from using the application.
				rv = null;
			}
			return rv;
		}
	}
}
